package cn.sciento.transfer.app.service.impl;

import cn.sciento.core.domain.Page;
import cn.sciento.core.exception.CommonException;import io.choerodon.mybatis.pagehelper.PageHelper;
import io.choerodon.mybatis.pagehelper.domain.PageRequest;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import javax.validation.Validator;
import org.apache.commons.collections4.CollectionUtils;
import cn.sciento.core.base.BaseConstants;
import cn.sciento.core.util.ValidUtils;
import cn.sciento.transfer.app.service.ConsDbConfigService;
import cn.sciento.transfer.app.service.ConsTenantConfigService;
import cn.sciento.transfer.app.service.TransferRedisService;
import cn.sciento.transfer.domain.entity.ConsDbConfig;
import cn.sciento.transfer.domain.entity.ConsTenantConfig;
import cn.sciento.transfer.domain.entity.ProducerConfig;
import cn.sciento.transfer.domain.repository.ConsDbConfigRepository;
import cn.sciento.transfer.domain.repository.ProducerConfigRepository;
import cn.sciento.transfer.infra.mapper.ConsDbConfigMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

@Service
public class ConsDbConfigServiceImpl implements ConsDbConfigService {
  @Autowired
  private ConsDbConfigRepository consDbConfigRepository;
  
  @Autowired
  private ConsTenantConfigService consTenantConfigService;
  
  @Autowired
  private ProducerConfigRepository producerConfigRepository;
  
  @Autowired
  private Validator validator;
  
  @Autowired
  private TransferRedisService transferRedisService;
  
  @Autowired
  private ConsDbConfigMapper consDbConfigMapper;
  
  @Transactional(rollbackFor = {Exception.class})
  public ConsDbConfig insertConsDbConfig(ConsDbConfig consDbConfig) {
    if (consDbConfig == null)
      return consDbConfig; 
    consDbConfig.init();
    ValidUtils.valid(this.validator, consDbConfig, new Class[0]);
    consDbConfig.validUnique(this.consDbConfigRepository);
    ProducerConfig producerConfig = (ProducerConfig)this.producerConfigRepository.selectByPrimaryKey(consDbConfig.getProducerConfigId());
    Assert.notNull(producerConfig, "error.data_not_exists");
    this.consDbConfigRepository.insertSelective(consDbConfig);
    if (CollectionUtils.isNotEmpty(consDbConfig.getConsTenantConfigList())) {
      if (Objects.equals(producerConfig.getTenantFlag(), BaseConstants.Flag.NO))
        throw new CommonException("error.cons.tenant.error");
      List<ConsTenantConfig> consTenantConfigList = consDbConfig.getConsTenantConfigList();
      consTenantConfigList.forEach(item -> item.init(consDbConfig.getProducerConfigId(), consDbConfig.getConsDbConfigId()));
      this.consTenantConfigService.batchInsertConsTenantConfig(consTenantConfigList);
    } 
    this.transferRedisService.addConsumerToRedis(producerConfig.getServiceCode(), producerConfig.getTableName(), consDbConfig);
    return consDbConfig;
  }
  
  @Transactional(rollbackFor = {Exception.class})
  public void deleteConsDbConfig(Long consDbConfigId) {
    ConsDbConfig consDbConfig = (ConsDbConfig)this.consDbConfigRepository.selectByPrimaryKey(consDbConfigId);
    ProducerConfig producerConfig = (ProducerConfig)this.producerConfigRepository.selectByPrimaryKey(consDbConfig.getProducerConfigId());
    Assert.notNull(consDbConfig, "error.data_not_exists");
    this.consDbConfigRepository.deleteByPrimaryKey(consDbConfigId);
    this.consTenantConfigService.deleteConsTenantConfig(consDbConfigId);
    this.transferRedisService.removeConsumerFromRedis(producerConfig.getServiceCode(), producerConfig.getTableName(), consDbConfig);
  }
  
  @Transactional(rollbackFor = {Exception.class})
  public void batchDeleteConsDbConfig(List<ConsDbConfig> consDbConfigs) {
    if (CollectionUtils.isNotEmpty(consDbConfigs))
      consDbConfigs.forEach(item -> deleteConsDbConfig(item.getConsDbConfigId())); 
  }
  
  @Transactional(rollbackFor = {Exception.class})
  public ConsDbConfig updateConsDbConfig(ConsDbConfig consDbConfig) {
    this.consDbConfigRepository.updateOptional(consDbConfig, new String[] { "consumerOffset", "enabledFlag" });
    List<ConsTenantConfig> consTenantConfigList = consDbConfig.getConsTenantConfigList();
    if (CollectionUtils.isEmpty(consTenantConfigList))
      return consDbConfig; 
    List<ConsTenantConfig> insertList = (List<ConsTenantConfig>)consTenantConfigList.stream().filter(item -> (item.getConsTenantConfigId() == null)).collect(Collectors.toList());
    ProducerConfig producerConfig = (ProducerConfig)this.producerConfigRepository.selectByPrimaryKey(consDbConfig.getProducerConfigId());
    Assert.notNull(producerConfig, "error.data_not_exists");
    if (CollectionUtils.isNotEmpty(insertList)) {
      if (Objects.equals(producerConfig.getTenantFlag(), BaseConstants.Flag.NO))
        throw new CommonException("error.cons.tenant.error");
      insertList.forEach(item -> item.init(consDbConfig.getProducerConfigId(), consDbConfig.getConsDbConfigId()));
      this.consTenantConfigService.batchInsertConsTenantConfig(insertList);
    } 
    this.transferRedisService.addConsumerToRedis(producerConfig.getServiceCode(), producerConfig.getTableName(), consDbConfig);
    return consDbConfig;
  }
  
  public Page<ConsDbConfig> pageAndSortConsDbConfig(PageRequest pageRequest, ConsDbConfig consDbConfig) {
    return this.consDbConfigRepository.pageAndSortConsDbConfig(pageRequest, consDbConfig);
  }
  
  public ConsDbConfig selectConsDbConfig(Long consDbConfigId) {
    return this.consDbConfigRepository.selectConsDbConfig(consDbConfigId);
  }
  
  public Page<ConsDbConfig> pageDataCheckTargetTable(PageRequest pageRequest, ConsDbConfig consDbConfig) {
    return PageHelper.doPageAndSort(pageRequest, () -> this.consDbConfigMapper.listDataCheckConsDbConfig(consDbConfig));
  }
}
